package com.fouram.web.utils;

import com.fouram.core.exception.BizException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;

import java.util.*;

@Slf4j
public class TreeUtils {

	public static <T> List<T> buildSimple(List<T> list) {
		return build(list, "id", "parentId", "children", "id", true, "0");
	}

	public static <T> List<T> build(List<T> list, String idProperty, String parentIdProperty,
											  String childrenProperty, String sortProperty, boolean asc, String rootValue) {
		// 转换成Map
		Map<String, List<T>> listMap = toMap(list, parentIdProperty);
		return buildSubTree(listMap, idProperty, parentIdProperty, childrenProperty, sortProperty, asc, rootValue);
	}

	private static <T> Map<String, List<T>> toMap(List<T> list, String parentIdProperty) {
		// 转换成Map
		Map<String, List<T>> listMap = Maps.newHashMap();
		for (T t : list) {
			try {
				String parentId = PropertyUtils.getProperty(t, parentIdProperty).toString();
				List<T> subList = Lists.newArrayList();
				if (listMap.containsKey(parentId)) {
					subList = listMap.get(parentId);
				}
				subList.add(t);
				listMap.put(parentId, subList);
			}catch (Exception e){
				log.error("transformation error :" ,e);
				throw new BizException("TreeUtils转换报错");
			}
		}
		return listMap;
	}

	/**
	 * 递归不断获取子节点，放到children属性
	 *
	 * @param <T>
	 * @param listMap
	 * @param idProperty
	 * @param parentIdProperty
	 * @param childrenProperty
	 * @param sortProperty
	 * @param asc
	 * @param parentValue
	 * @return
	 * @throws Exception
	 */
	private static <T> List<T> buildSubTree(Map<String, List<T>> listMap, String idProperty, String parentIdProperty,
											String childrenProperty, String sortProperty, boolean asc, String parentValue){
		List<T> result = new LinkedList<>();
		List<T> subList = new LinkedList<>();
		if (listMap.containsKey(parentValue.toString())) {
			subList = listMap.get(parentValue.toString());
		}
		Collections.sort(subList, (Comparator<Object>) (o1, o2) -> {
			Object sort1 = "0";
			Object sort2 = "0";
			try {
				sort1 = PropertyUtils.getProperty(o1, sortProperty);
				sort2 = PropertyUtils.getProperty(o2, sortProperty);
			} catch (Exception e) {
				log.error("build sub tree error" ,e);
			}
			if (asc) {
				return Integer.valueOf(sort1.toString()).intValue() - Integer.valueOf(sort2.toString()).intValue();
			} else {
				return Integer.valueOf(sort2.toString()).intValue() - Integer.valueOf(sort1.toString()).intValue();
			}
		});
		for (int i = 0; i < subList.size(); i++) {
			try {

				T obj = subList.get(i);
				String id = PropertyUtils.getProperty(obj, idProperty).toString();
				PropertyUtils.setProperty(obj, childrenProperty,
						buildSubTree(listMap, idProperty, parentIdProperty, childrenProperty, sortProperty, asc, id));
				result.add(obj);
			}catch (Exception e){
				log.error("buildSubTree error",e);
				throw new BizException("TreeUtils转换报错");
			}
		}
		return result;
	}
}
